

/*
*Released on 28th June 2008.
*Any violations can be reported at paritosh@wikiocean.net
*What is treated as violations can be found at www.wikiocean.net/ppl1-voilations*
******************************************************************************
* The contents of this file are subject to POOL Public License 1.0 and later.
* POOL Public License is based on Affero GPL v3 and additional conditions.
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the Affero GPL v3 License at http://www.gnu.org/licenses/agpl.html
* You may obtain a copy of the POOL Public License 1.0 or later at www.wikiocean.net/license/ppl.html
* Software distributed under POOL Public License 1.0 is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Initial Developer of the Original Code is Paritosh Pungaliya (C) 2008. All Rights Reserved.
******************************************************************************
* Objective of the additional terms (license)
* 1) Is to extend the software freedom to freedom to work.
* 2) To ensure that knowledge is free from monopoly of agencies.
* 3) To avoid a situation where big corporate or investor can buy out free software groups and companies and then start milking the communities built around it.
* (this trend can be seen how the freedom is curtailed in companies that get Venture Capital funding.)
******************************************************************************
*/

package  event;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import control.RequestParameter;
import pool.bean.Master_table_Bean;
import dbmanager.DBManager;
import dbmanager.DBOperation;

/**
 * @author Divyesh
 * 
 * This class will defined the mapping of objects into the database automatically.
 * Here we have to specifies the common mapping of the objects, Unique key(s) & their sample value(s), table name 
 * and all other taken as automatically from the Metadata of the table.
 * 
 * Here you required two database connection 1st for the product(likes OB, Sugar, etc.) database 
 * and another for the POOL database. 
 * 
 * NOTICE: Before using this class, please keep in mind that every column name or field name
 * must be present into the database of POOL. Otherwise it will behaves like anything.
 * So, first enter each & every properties as a default property named "attribute" and then only use this script.
 * 
 * Revision-0 :
 * Now you can just specifies the common mapping of the objects, Unique key(s) & their sample value(s), table name 
 * and all other taken as automatically from the Metadata of the table.
 * 
 * So, here we had removed above NOTICE problem. Now, it will add the properties with default property "Attribute".
 * And for registered properties it will generates the message like "Property already present." 
 */

public class AutoMappingObjects {
	private Hashtable<Object, Object> columnField = new Hashtable<Object, Object>();
	private String tableName = "";
//	private String uniqueKey = "";
	private Hashtable<Object, Object> condition = new Hashtable<Object, Object>();
	private Vector<Object> uniqueVector = new Vector<Object>();
	
	RequestParameter req;
	Master_table_Bean mtb = new Master_table_Bean();
	DBOperation integratedDB = new DBOperation("org.postgresql.Driver","jdbc:postgresql:","//localhost/openbravo","postgres","postgres");
	
	public AutoMappingObjects() { }
	
	public AutoMappingObjects(String tableName, Hashtable<Object, Object> columnField)
	{
		integratedDB.getConnect(); // Product database connection.
		
		this.columnField = columnField;
		this.tableName = tableName;
		
		// Setting Request Parameter properties.
		req = new RequestParameter();	
		req.setUsername("+919922918605");
		req.setPassword("605");
		req.setProcess("add");
		req.setVersion("11");
		req.setMessage("");
		req.setRequest("master_table");
		
		// Setting master_table_bean properties.
		mtb.setReqParam(req);
	}
	
	/** It will register all the column name as a "Attribute", if the column name does not present into the POOL database.*/
	public void getAttributeRegister() {
		ResultSet rs = integratedDB.getselect(condition, tableName); // Here you need to use Product database connection.
		int i=1;
    	try {
			while(i!=rs.getMetaData().getColumnCount()+1)
			{		
				String col = rs.getMetaData().getColumnName(i).toString();
				Hashtable<Object, Object> temp = new Hashtable<Object, Object>();
				temp.put("Type", "attribute");
				//Vector<Object> propertyVector = new Vector<Object>();
				mtb.setNewMasterObject(col);
				mtb.setPropertyVector(getPoolVector(col, temp));
				mtb.insert();
			}
			rs.close();
    	}catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**It will create whole mapping related to integration into the database.*/
	public void getMapped() {
	
		Vector<Object> fielListVector = new Vector<Object>();
		
		ResultSet rs = integratedDB.getselect(condition, tableName); // Here you need to use Product database connection.
		int i=1;
    	try {
			while(i!=rs.getMetaData().getColumnCount()+1)
			{		
				Vector<Object> propertyVector = new Vector<Object>();
				Hashtable<Object, Object> mappingObjects = new Hashtable<Object, Object>();
				Hashtable<Object, Object> fieldList = new Hashtable<Object, Object>();
				mappingObjects.put("type", "Field");
				
				String col = rs.getMetaData().getColumnName(i).toString();
				//String value = rs.getString(col);
				String fieldMaster = "fieldObj_" + col; 
			
				if(columnField.containsKey(col))
				{
					mappingObjects.put("Column", col);
					mappingObjects.put("Field", columnField.get(col));
				}
				else
				{
					mappingObjects.put("Column", col);
					mappingObjects.put("Field", col);
				}
				propertyVector.addAll(getPoolVector(fieldMaster, mappingObjects)); // To Convert into the pool format.
				System.out.println("Field Object Master : " + fieldMaster + " \tField Object : " + propertyVector);
				// It will insert Field object into the database.
				mtb.setNewMasterObject(fieldMaster);
				mtb.setPropertyVector(propertyVector);
				mtb.insert();
				
				fieldList.put("field", fieldMaster); // It will create FieldList object.
				fielListVector.add(fieldList);
				i++;
			}
			rs.close();
			// It will creates the FieldList Object.
			String fieldListMaster = "fieldListobj_" + tableName;
			Hashtable<Object, Object> temp = new Hashtable<Object, Object>();
			temp.put("Type", "Fieldlist");
			fielListVector.add(temp);
			fielListVector.addAll(getPoolVecFromVec(fieldListMaster, fielListVector));
			System.out.println("FieldList Object Master : " + fieldListMaster + " \tField List Object : " + fielListVector);
			
			// It will insert FieldList object into the database.
			mtb.setNewMasterObject(fieldListMaster);
			mtb.setPropertyVector(fielListVector);
			mtb.insert();
			
			// It will creates the table Object.
			getTableMapped(fieldListMaster); // Call to table object mapping.
			
			integratedDB.closeConnection();
			integratedDB = null;
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**It will creates Table Object into the database.*/
	private void getTableMapped(String fieldList) {
		Hashtable<Object, Object> tableHash = new Hashtable<Object, Object>();
		tableHash.put("Type", "table");
		tableHash.put("Tablename", tableName);
		tableHash.put("Fieldlist", fieldList);
		tableHash.put("unique", getUniqueObject()); // Call to uniqueObject mapping.
		
		String tableMaster = "tableObj_" + tableName;
		
		Vector<Object> tableVec = new Vector<Object>();
		tableVec.addAll(getPoolVector(tableMaster, tableHash));
		System.out.println("Table Object Master : " + tableMaster + " \tTable Object : " + tableVec);
		
		// It will insert table object into the database.
		mtb.setNewMasterObject(tableMaster);
		mtb.setPropertyVector(tableVec);
		mtb.insert();
	}
	
	/**It will creates Unique Key Object into the database.*/
	private String getUniqueObject() {
		Hashtable<Object, Object> unique = new Hashtable<Object, Object>();
		unique.put("Type", "unique");
		String uniqueMaster = "uniqueObj_" + tableName;
	
		uniqueVector.add(unique);
		uniqueVector.addAll(getPoolVecFromVec(uniqueMaster, uniqueVector));
		System.out.println("Unique Object Master : " + uniqueMaster + " \tTable Object : " + uniqueVector);		
		// It will insert uniqueKey object into the database.
		mtb.setNewMasterObject(uniqueMaster);
		mtb.setPropertyVector(uniqueVector);
		mtb.insert();
		return uniqueMaster;
	}
	
	/** It will creates the unique key vector and also condition object.
	 * @param uniqueKey - List of unique or Primary keys.
	 * @param uniqueKeyValue - Sample value of the keys.
	 * */
	public Hashtable<Object, Object> getUniqueKeyHash(String[] uniqueKey, String[] uniqueKeyValue) {
		Hashtable<Object, Object> uniqueCondition = new Hashtable<Object, Object>();
		
		for(int i = 0; i < uniqueKey.length; i++)
		{			
			uniqueCondition.put(uniqueKey[i], uniqueKeyValue[i]);
			// For storing unique key(s).
			Hashtable<Object, Object> temp = new Hashtable<Object, Object>();
			temp.put("Column", uniqueKey[i]);			
			uniqueVector.add(temp);
		}		
		return uniqueCondition;
	}
	
	/**It will generates the vector from Hashtable, for pool input like mid, pid, pv form.
	 * @param master - master object name or mid
	 * @param property - propertyHash, which we need to convert into the form of mid, pid, pv means in POOL format. 
	 * */
	private Vector<Object> getPoolVector(String master, Hashtable<Object, Object> property) {
		Vector<Object> propertyVec = new Vector<Object>();
		Enumeration<Object> keys = property.keys();
		while(keys.hasMoreElements())
		{
			Hashtable<Object, Object> temp = new Hashtable<Object, Object>();
			String key = keys.nextElement().toString();
			String value = property.get(key).toString();
		//	temp.put("mid", master);
			temp.put("pid", key);
			temp.put("pv", value);
			propertyVec.add(temp);
		}
		return propertyVec;
	}
	
	/**It will generates the vector from Vector, for pool input like mid, pid, pv form.
	 * @param master - master object name or mid
	 * @param property - property vector, which we need to convert into the form of mid, pid, pv means in POOL format. 
	 * */
	@SuppressWarnings("unchecked")
	private Vector<Object> getPoolVecFromVec(String master, Vector<Object> property) {
		Vector<Object> propertyVec = new Vector<Object>();
				
		for(int i = 0; i < property.size(); i++)
		{
			Hashtable<Object, Object> temp = new Hashtable<Object, Object>();
			temp.putAll((Hashtable<Object, Object>)property.get(i));
			Enumeration<Object> keys = temp.keys();
			while(keys.hasMoreElements())
			{
				Hashtable<Object, Object> temp1 = new Hashtable<Object, Object>();
				String key = keys.nextElement().toString();
				String value = temp.get(key).toString();
		//		temp1.put("mid", master);
				temp1.put("pid", key);
				temp1.put("pv", value);
				propertyVec.add(temp1);
			}
		}		
		return propertyVec;
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {	
		String tableName = "m_product";
		String uniqueKey[] = {"m_product_id"};
		String uniqueKeyValue[] = {"1000000"};
		
		Hashtable<Object, Object> columnField = new Hashtable<Object, Object>();
		columnField.put("m_product_id", "id");
		columnField.put("name", "first_name");
		
		AutoMappingObjects map = new AutoMappingObjects(tableName, columnField);
		
		Hashtable<Object, Object> condition = new Hashtable<Object, Object>();
		condition.putAll(map.getUniqueKeyHash(uniqueKey, uniqueKeyValue)); // Generates the query condition.
		map.condition.putAll(condition);
		map.getAttributeRegister(); 
		map.getMapped();
	}
}
